package View;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.WindowEvent;
import java.awt.event.WindowFocusListener;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.ArrayList;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.JTabbedPane;
import javax.swing.JTable;
import javax.swing.JTextPane;
import javax.swing.JToolBar;
import javax.swing.KeyStroke;
import javax.swing.SpringLayout;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.table.DefaultTableModel;
import javax.swing.text.DefaultStyledDocument;
import javax.swing.text.StyleContext;

import ViewListener.MainViewActionListener;
import ViewListener.SqlDocumentListener;
import ViewListener.SqlEditorThread;


public class MainView extends MyView{

	private DefaultTableModel tableModel;
	private JScrollPane resultPanel;
	private JPanel panel;
	private MainViewActionListener actionListener;
	private SpringLayout resultLayout;
	private ArrayList<JComponent> resultItems = new ArrayList<JComponent>();
	private JTextPane sqlEditor;
	private SqlEditorThread editorHighlightThread;
	private SqlDocumentListener documentListener;
	/**
	 * Create the application.
	 */
	public MainView(String name) {
		super(name);
		actionListener = new MainViewActionListener();		
		initialize();
	}

	/**
	 * Initialize the contents of the frame.
	 */
	private void initialize() {
		
		try {
			UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InstantiationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (UnsupportedLookAndFeelException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		frame = new JFrame();		
		frame.setIconImage(Toolkit.getDefaultToolkit().getImage("img\\key.png"));
		frame.setTitle("SQL client");
		frame.setBounds(100, 100, 800, 600);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		SpringLayout springLayout = new SpringLayout();
		frame.getContentPane().setLayout(springLayout);
		
		initializeMenuBar();
		
		JToolBar toolBar = new JToolBar();		
		springLayout.putConstraint(SpringLayout.NORTH, toolBar, 0, SpringLayout.NORTH, frame.getContentPane());
		springLayout.putConstraint(SpringLayout.WEST, toolBar, 0, SpringLayout.WEST, frame.getContentPane());
		springLayout.putConstraint(SpringLayout.EAST, toolBar, 0, SpringLayout.EAST, frame.getContentPane());
		frame.getContentPane().add(toolBar);
		
		JButton btnExecute = new JButton("Execute");
		btnExecute.addActionListener(actionListener);
		btnExecute.setIcon(new ImageIcon("img\\execute24x24.png"));
		toolBar.add(btnExecute);
		
		JButton btnClear = new JButton("Clear");
		btnClear.addActionListener(actionListener);
		btnClear.setIcon(new ImageIcon("img\\delete24x24.png"));
		toolBar.add(btnClear);
		
		JTabbedPane tabbedPane = new JTabbedPane(JTabbedPane.TOP);
		springLayout.putConstraint(SpringLayout.NORTH, tabbedPane, 6, SpringLayout.SOUTH, toolBar);
		springLayout.putConstraint(SpringLayout.WEST, tabbedPane, 0, SpringLayout.WEST, frame.getContentPane());
		springLayout.putConstraint(SpringLayout.EAST, tabbedPane, 0, SpringLayout.EAST, frame.getContentPane());
		frame.getContentPane().add(tabbedPane);
		
		StyleContext sc = new StyleContext();		
		DefaultStyledDocument defaultStyle = new DefaultStyledDocument(sc);		
		sqlEditor = new JTextPane(defaultStyle);		
		// Sql Text Pane check for high light
		editorHighlightThread = new SqlEditorThread(sqlEditor, defaultStyle);
		sqlEditor.setEditable(true);		
		documentListener = new SqlDocumentListener(editorHighlightThread);
		sqlEditor.getDocument().addDocumentListener(documentListener);
		JScrollPane scrollSQL = new JScrollPane(sqlEditor); 
		tabbedPane.addTab("SQL", null, scrollSQL, null);		
		
		
		// Result parent panel
		panel = new JPanel();
		resultPanel = new JScrollPane(panel);
		
		springLayout.putConstraint(SpringLayout.SOUTH, tabbedPane, -6, SpringLayout.NORTH, resultPanel);
		springLayout.putConstraint(SpringLayout.NORTH, resultPanel, 322, SpringLayout.NORTH, frame.getContentPane());
		springLayout.putConstraint(SpringLayout.WEST, resultPanel, 0, SpringLayout.WEST, frame.getContentPane());
		springLayout.putConstraint(SpringLayout.SOUTH, resultPanel, -10, SpringLayout.SOUTH, frame.getContentPane());
		springLayout.putConstraint(SpringLayout.EAST, resultPanel, 0, SpringLayout.EAST, frame.getContentPane());
		panel.setBackground(Color.WHITE);
		
		frame.getContentPane().add(resultPanel);
		resultLayout = new SpringLayout();
		panel.setLayout(resultLayout);
		
		JSeparator separator = new JSeparator();
		resultLayout.putConstraint(SpringLayout.NORTH, separator, 0, SpringLayout.NORTH, panel);
		resultLayout.putConstraint(SpringLayout.WEST, separator, 0, SpringLayout.WEST, panel);
		resultLayout.putConstraint(SpringLayout.SOUTH, separator, 2, SpringLayout.NORTH, panel);
		resultLayout.putConstraint(SpringLayout.EAST, separator, 0, SpringLayout.EAST, panel);
		panel.add(separator);
		
		JLabel lblResult = new JLabel("Result:");
		resultLayout.putConstraint(SpringLayout.NORTH, lblResult, 6, SpringLayout.SOUTH, separator);
		resultLayout.putConstraint(SpringLayout.WEST, lblResult, 10, SpringLayout.WEST, separator);
		lblResult.setAlignmentY(Component.LEFT_ALIGNMENT);		
		panel.add(lblResult);	
		
		setWindowsFocusListener(sqlEditor);
	}

	private void setWindowsFocusListener(final JEditorPane sqlEditor) {
		// Set focus on text are
		frame.addWindowFocusListener(new WindowFocusListener() {
			
			@Override
			public void windowLostFocus(WindowEvent arg0) {
				// TODO Auto-generated method stub
				
			}
			
			@Override
			public void windowGainedFocus(WindowEvent arg0) {
				// TODO Auto-generated method stub
				sqlEditor.requestFocusInWindow();
			}
		});
	}

	private void initializeMenuBar() {
		// Menu Bar
		JMenuBar menuBar = new JMenuBar();
		{
			// File menu
			JMenu fileMenu = new JMenu("File");
			fileMenu.setMnemonic(KeyEvent.VK_F);
			{
				// Open item
				JMenuItem openItem = new JMenuItem("Open");
				openItem.setAccelerator(KeyStroke.getKeyStroke(
				        KeyEvent.VK_O, ActionEvent.CTRL_MASK));
				openItem.setMnemonic(KeyEvent.VK_O);
				openItem.addActionListener(actionListener);
				fileMenu.add(openItem);
				
				// Save item
				JMenuItem saveItem = new JMenuItem("Save as");
				saveItem.setAccelerator(KeyStroke.getKeyStroke(
				        KeyEvent.VK_S, ActionEvent.CTRL_MASK));
				saveItem.setMnemonic(KeyEvent.VK_S);
				saveItem.addActionListener(actionListener);
				fileMenu.add(saveItem);
				
				// Exit item
				JMenuItem exitItem = new JMenuItem("Exit");
				exitItem.setMnemonic(KeyEvent.VK_X);
				exitItem.addActionListener(actionListener);
				fileMenu.add(exitItem);
				
			}
			
			menuBar.add(fileMenu);
			
			// Run menu
			JMenu runMenu = new JMenu("Run");
			fileMenu.setMnemonic(KeyEvent.VK_R);
			{
				// Execute item
				JMenuItem executeItem = new JMenuItem("Execute");				
				executeItem.setMnemonic(KeyEvent.VK_E);
				executeItem.setAccelerator(KeyStroke.getKeyStroke(
				        KeyEvent.VK_F5, ActionEvent.CTRL_MASK));
				executeItem.addActionListener(actionListener);
				runMenu.add(executeItem);

				JMenuItem clearItem = new JMenuItem("Clear!");
				clearItem.setMnemonic(KeyEvent.VK_R);
				clearItem.setAccelerator(KeyStroke.getKeyStroke(
				        KeyEvent.VK_D, ActionEvent.CTRL_MASK));
				executeItem.addActionListener(actionListener);
				runMenu.add(clearItem);
			}
			
			menuBar.add(runMenu);
		}
		
		frame.setJMenuBar(menuBar);
	}
	
	public void ClearAllItemInResult()
	{		
		JComponent component;
		while(resultItems.size() > 0)
		{
			component = resultItems.get(resultItems.size() - 1);
			panel.remove(component);			
			resultItems.remove(component);			
			component = null;
			panel.repaint();
			panel.validate();
		}
		panel.setPreferredSize(new Dimension(0, 0));
		
	}
	
	public void AddItemToResult(JComponent component)
	{
		JComponent lastItem = null;
		int heightDistance = 15;
		int widthDistance = 23;
				
		// Empty
		if(resultItems.size() > 0)
		{
			// Check exist
			if(resultItems.contains(component))
				return;
			
			lastItem = resultItems.get(resultItems.size() - 1);
			resultLayout.putConstraint(SpringLayout.NORTH, component, heightDistance, SpringLayout.SOUTH, lastItem);
			resultLayout.putConstraint(SpringLayout.WEST, component, widthDistance, SpringLayout.WEST, panel);
		}
		else
		{
			// Have item
			lastItem = panel;
			heightDistance = 25;
			resultLayout.putConstraint(SpringLayout.NORTH, component, heightDistance, SpringLayout.NORTH, lastItem);
			resultLayout.putConstraint(SpringLayout.WEST, component, widthDistance, SpringLayout.WEST, panel);
		}		
		
		Dimension lastPanelPreferredSize = panel.getPreferredSize();
		Dimension componentPreferredSize = component.getPreferredSize();
		
		if(component instanceof JScrollPane)
		{
			Component c = component.getComponent(0);
			componentPreferredSize = c.getPreferredSize();
			componentPreferredSize.height += 32;
		}
		panel.add(component);		
		int width = (lastPanelPreferredSize.width > componentPreferredSize.width) ? lastPanelPreferredSize.width : componentPreferredSize.width + 30;
		int height = lastPanelPreferredSize.height + componentPreferredSize.height + heightDistance;
		panel.setPreferredSize(new Dimension(width, height));
		resultItems.add(component);	

		panel.repaint();
		component.repaint();
		panel.validate();
		component.validate();
		resultPanel.repaint();
		resultPanel.validate();
	}
	
	public JScrollPane createNewResultTable(Object[] columnsName, Object[][] data)
	{		
		tableModel = new DefaultTableModel(data, columnsName);	
		
		JTable table = new JTable(tableModel){
			 /**
			 * 
			 */
			private static final long serialVersionUID = -6486903453385403355L;

			public boolean isCellEditable(int rowIndex, int colIndex) {
				  return false; //Disallow the editing of any cell
				  }
		};
		
		int width = table.getColumnCount() * 50;
		int height = (table.getRowCount())* table.getRowHeight();
		table.setPreferredScrollableViewportSize(new Dimension(width, height));
		JScrollPane scrollPane = new JScrollPane(table);
		return scrollPane;
	}
	
	public String getSQL()
	{
		return sqlEditor.getText();
	}
	
	public void clearAllSQL()
	{
		sqlEditor.setText("");
	}
	
	public void setSQL(String sql)
	{
		sqlEditor.setText(sql);
	}
	
	public boolean isComment(int index)
	{
		return editorHighlightThread.isCommentStyle(index);
	}
	
	public void loadSQLFromFile(String path) throws FileNotFoundException
	{
		clearAllSQL();
		String sql = "";
		
		try
		{
			FileInputStream fstream = new FileInputStream(path);
			DataInputStream in = new DataInputStream(fstream);
			BufferedReader br = new BufferedReader(new InputStreamReader(in));
			String strLine;
			while ((strLine = br.readLine()) != null)  
			{
				sql += strLine;
				sql += "\r\n";
			}
	
			
			in.close();
		}
		catch (Exception e)
		{
			setSQL(sql);
			System.err.println("Error: " + e.getMessage());
		}
		
		setSQL(sql);
		documentListener.insertUpdate(null);
	}
	
	public void saveSQLToFile(String path) throws IOException
	{
		System.out.println(path);
		String sql = getSQL();
		
		try
		{
			FileOutputStream fstream = new FileOutputStream(path);
			DataOutputStream out = new DataOutputStream(fstream);
			BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(out));
			bw.write(sql);
			bw.close();
		}
		catch (Exception e)
		{
			System.err.println("Error: " + e.getMessage());
		}	
		 
	}
}
